package com.progenies.ecg.model;

import com.progenies.ecg.model.codeparts.lines.LineCodePart;

/**
 * Specifies a reference to an existent variable
 * @author ofc587a87
 *
 */
public class ValueReference<T>
{
	private String name;
	private String ownerVariable;
	private Class<T> ownerClass;
	private T staticValue;
	private LineCodePart executionLine;
	
	private ValueReference()
	{
	}
	
	public static final ValueReference<Object> forVariable(String variableName)
	{
		ValueReference<Object> ref=new ValueReference<Object>();
		ref.name=variableName;
		return ref;
	}

	public static final ValueReference<Object> forFieldInVariable(String fieldName, String ownerName)
	{
		ValueReference<Object> ref=new ValueReference<Object>();
		ref.name=fieldName;
		ref.ownerVariable=ownerName;
		return ref;
	}

	public static final <E> ValueReference<E> forStaticFieldInClass(String fieldName, Class<E> ownerClass)
	{
		ValueReference<E> ref=new ValueReference<E>();
		ref.name=fieldName;
		ref.ownerClass=ownerClass;
		return ref;
	}

	public static final <T> ValueReference<T> forStaticValue(T value)
	{
		if(value!=null && !isPrimitiveOrWrapper(value) && !(value instanceof String))
			throw new RuntimeException("Only constant values accepted (primitives or String)");
		ValueReference<T> ref=new ValueReference<T>();
		ref.staticValue=value;
		return ref;
	}
	
	
	public static final ValueReference<Object> forExecutionResult(LineCodePart executionInstruction)
	{
		if(executionInstruction==null)
			throw new RuntimeException("Only constant values accepted (primitives or String)");
		ValueReference<Object> ref=new ValueReference<Object>();
		ref.executionLine=executionInstruction;
		return ref;
	}
	
	private static boolean isPrimitiveOrWrapper(Object obj)
	{
		if(obj.getClass().isPrimitive())
			return true;
		else if(obj instanceof Integer ||
				obj instanceof Long ||
				obj instanceof Character  ||
				obj instanceof Short ||
				obj instanceof Byte ||
				obj instanceof Double ||
				obj instanceof Float ||
				obj instanceof Boolean)
			return true;
		else
			return false;
	}
	
	
	

	public String getName() {
		return name;
	}
	
	public T getStaticValue() {
		return staticValue;
	}

	public String getOwnerVariable() {
		return ownerVariable;
	}

	public Class<T> getOwnerClass() {
		return ownerClass;
	}

	public LineCodePart getExecutionLine() {
		return executionLine;
	}


	
	

}
